import { Noise } from "../tool/Noise"
import { util } from "../tool/Util"
import { MainUI } from "../ui/MainUI"

export class LevelModuleData extends Subdata{

}

export class LevelModuleC extends ModuleC<LevelModuleS,LevelModuleData>{
    private basicDeep = -2000
    private currentLevel = 1
    private levelIncreaseDeep = 400
    private getLevelBorder():Type.Vector2{
        let endPlaneSize = this.endPlane.worldScale
        return new Type.Vector2(endPlaneSize.x * 50, endPlaneSize.y * 50)
    }

    private endPlane:Core.GameObject
    private playerSpawnPoint:Core.GameObject
    private characterTrigger:Gameplay.Trigger
    private wall:Core.GameObject
    private barrierBuffer:Core.GameObject[] = []

    private landBottom:Core.GameObject
    private landLeft:Core.GameObject
    private landRight:Core.GameObject
    private landTop:Core.GameObject

    protected onStart(): void {
        // this.currentPlayer.character.switchToFlying()

        this.landBottom = Core.GameObject.find("118DD70F")
        this.landLeft = Core.GameObject.find("16F4C4F1")
        this.landRight = Core.GameObject.find("07212F48")
        this.landTop = Core.GameObject.find("393F319D")

        this.playerSpawnPoint = Core.GameObject.find('DC5A4E2B47A0C6E31572FE9882BE6861')

        this.wall = Core.GameObject.find('3591CD1E')

        this.characterTrigger = Core.GameObject.spawn({guid:"Trigger",replicates:false}) 
        this.characterTrigger.onEnter.add(this.onCharacterTriggered.bind(this))
        this.currentPlayer.character.attach(this.characterTrigger,Gameplay.SlotType.Root)
        this.characterTrigger.worldScale = new Type.Vector(0.8,0.8,1.9)
        this.characterTrigger.relativeLocation = new Type.Vector(0,0,85)

        this.endPlane = Core.GameObject.spawn({guid:"197386",replicates:false})
        this.endPlane.worldLocation = new Type.Vector(0,0,1e7)
        this.endPlane.worldScale = new Type.Vector(20,20,0.5)
        this.endPlane.setCollision(Type.CollisionStatus.On)
 
        this.buildLevel()

        UI.UIManager.instance.show(MainUI)
    }


    private buildLevel(){
        
        console.error(`当前关卡：${this.currentLevel}`);

        let deep = this.getLevelDeep()

        if(this.barrierBuffer.length > 0){
            for (const barrier of this.barrierBuffer) {
                Extension.GameObjPool.getInstance().despawn(barrier)
            }
            this.barrierBuffer = []
        }
        
        // 终点
        this.endPlane.worldLocation = new Type.Vector(0,0,deep)
        // 边墙
        this.wall.worldLocation = new Type.Vector(0,0,deep)
        this.wall.worldScale = new Type.Vector(this.endPlane.worldScale.x, this.endPlane.worldScale.y, -deep / 100)
        // 平台
        let hollowTS = util.getHollowSquareTS(this.wall.worldScale.x * 100, 500, 100, new Type.Vector2(-this.wall.worldScale.x * 50,-this.wall.worldScale.x * 50))
        this.landBottom.worldLocation = new Type.Vector(hollowTS.bottom.x,hollowTS.bottom.y,0);
        this.landLeft.worldLocation = new Type.Vector(hollowTS.left.x,hollowTS.left.y,0);
        this.landRight.worldLocation = new Type.Vector(hollowTS.right.x,hollowTS.right.y,0);
        this.landTop.worldLocation = new Type.Vector(hollowTS.top.x,hollowTS.top.y,0);
        this.landBottom.worldScale = new Type.Vector(hollowTS.bottom.z,hollowTS.bottom.w,1)
        this.landLeft.worldScale = new Type.Vector(hollowTS.left.z,hollowTS.left.w,1)
        this.landRight.worldScale = new Type.Vector(hollowTS.right.z,hollowTS.right.w,1)
        this.landTop.worldScale = new Type.Vector(hollowTS.top.z,hollowTS.top.w,1);
        // 障碍物
        let barrierCount = this.getBarrierCount()
        for(let i = 1;i < barrierCount;i++){
            let barrier = <Gameplay.Mesh> Extension.GameObjPool.getInstance().spawn("197386", Extension.GameObjPoolSourceType.Asset)
            barrier.setCollision(Type.CollisionStatus.QueryOnly)
            barrier.setMaterial('378432A84B1D5F5DC44ACD90363B3DBB')

            let randomScaleX = Math.max(Math.abs(Noise.random(i + this.currentLevel)), 0.1) * 10
            let randomScaleY = Math.max(Math.abs(Noise.random(i + this.currentLevel + 10)), 0.1) * 10
            barrier.worldScale = new Type.Vector(randomScaleX,randomScaleY,0.5)
            
            let randomVector = Noise.randomV2(i + this.currentLevel)
            let border = this.getLevelBorder()
            barrier.worldLocation = new Type.Vector(border.x * randomVector.x, border.y * randomVector.y, i * (deep / barrierCount))

            this.barrierBuffer.push(barrier)
        }
    }

    private onCharacterTriggered(other:Core.GameObject){
        // 通关
        if(other == this.endPlane){
            this.levelSuccess()
            return
        }
        // 碰到障碍物
        let barrierIndex = this.barrierBuffer.findIndex(barrier => {
            return barrier == other
        })
        if(barrierIndex != -1){
            this.levelFailed()
        }
    }
    
    private getLevelDeep():number{
        return this.basicDeep - this.levelIncreaseDeep * this.currentLevel
    }

    private getBarrierCount():number{
        let deep = -this.getLevelDeep()
        return Math.floor(deep / 250)
    }

    private levelSuccess(){
        this.currentPlayer.character.worldLocation = this.playerSpawnPoint.worldLocation
        this.currentLevel ++
        
        this.buildLevel()
    }

    private levelFailed(){
        this.currentPlayer.character.worldLocation = this.playerSpawnPoint.worldLocation
    }
}

export class LevelModuleS extends ModuleS<LevelModuleC,LevelModuleData>{
    
}